import * as cornerstoneTools from "@cornerstonejs/tools";
import { VolumeViewport, utilities as csUtils } from "@cornerstonejs/core";
import drawHandlesSvg from "./drawHandlesSvg";

const { Enums: csToolsEnums, ProbeTool, annotation, drawing } = cornerstoneTools;

const { ChangeTypes } = csToolsEnums;
const { getAnnotations } = annotation.state;
const { drawTextBox: drawTextBoxSvg } = drawing;

class MyProbeTool extends ProbeTool {
	static toolName = "MyProbe";

	constructor(options = {}) {
		super(options);
	}

	/**
	 * it is used to draw the probe annotation in each
	 * request animation frame. It calculates the updated cached statistics if
	 * data is invalidated and cache it.
	 *
	 * @param enabledElement - The Cornerstone's enabledElement.
	 * @param svgDrawingHelper - The svgDrawingHelper providing the context for drawing.
	 */
	renderAnnotation = (enabledElement, svgDrawingHelper) => {
		let renderStatus = false;
		const { viewport } = enabledElement;
		const { element } = viewport;

		let annotations = getAnnotations(this.getToolName(), element);

		if (!annotations?.length) {
			return renderStatus;
		}

		annotations = this.filterInteractableAnnotationsForElement(element, annotations);

		if (!annotations?.length) {
			return renderStatus;
		}

		const targetId = this.getTargetId(viewport);
		const renderingEngine = viewport.getRenderingEngine();

		const styleSpecifier = {
			toolGroupId: this.toolGroupId,
			toolName: this.getToolName(),
			viewportId: enabledElement.viewport.id
		};

		for (let i = 0; i < annotations.length; i++) {
			const annotation = annotations[i];
			const annotationUID = annotation.annotationUID;
			const data = annotation.data;
			const point = data.handles.points[0];
			const canvasCoordinates = viewport.worldToCanvas(point);

			styleSpecifier.annotationUID = annotationUID;

			const { color, lineWidth } = this.getAnnotationStyle({
				annotation,
				styleSpecifier
			});

			if (!data.cachedStats) {
				data.cachedStats = {};
			}

			if (!data.cachedStats[targetId] || data.cachedStats[targetId].value === null) {
				data.cachedStats[targetId] = {
					Modality: null,
					index: null,
					value: null
				};

				this._calculateCachedStats(
					annotation,
					renderingEngine,
					enabledElement,
					ChangeTypes.StatsUpdated
				);
			} else if (annotation.invalidated) {
				this._calculateCachedStats(annotation, renderingEngine, enabledElement);

				// If the invalidated data is as a result of volumeViewport manipulation
				// of the tools, we need to invalidate the related stackViewports data if
				// they are not at the referencedImageId, so that
				// when scrolling to the related slice in which the tool were manipulated
				// we re-render the correct tool position. This is due to stackViewport
				// which doesn't have the full volume at each time, and we are only working
				// on one slice at a time.
				if (viewport instanceof VolumeViewport) {
					const { referencedImageId } = annotation.metadata;

					// invalidate all the relevant stackViewports if they are not
					// at the referencedImageId
					for (const targetId in data.cachedStats) {
						if (targetId.startsWith("imageId")) {
							const viewports = renderingEngine.getStackViewports();

							const invalidatedStack = viewports.find(vp => {
								// The stack viewport that contains the imageId but is not
								// showing it currently
								const referencedImageURI = csUtils.imageIdToURI(referencedImageId);
								const hasImageURI = vp.hasImageURI(referencedImageURI);
								const currentImageURI = csUtils.imageIdToURI(
									vp.getCurrentImageId()
								);
								return hasImageURI && currentImageURI !== referencedImageURI;
							});

							if (invalidatedStack) {
								delete data.cachedStats[targetId];
							}
						}
					}
				}
			}

			// If rendering engine has been destroyed while rendering
			if (!viewport.getRenderingEngine()) {
				console.warn("Rendering Engine has been destroyed");
				return renderStatus;
			}

			const handleGroupUID = "0";

			drawHandlesSvg(svgDrawingHelper, annotationUID, handleGroupUID, [canvasCoordinates], {
				color,
				lineWidth,
				handleRadius: this.configuration.handleRadius,
				type: "path"
			});

			renderStatus = true;

			const options = this.getLinkedTextBoxStyle(styleSpecifier, annotation);
			if (!options.visibility) {
				continue;
			}

			const textLines = this.configuration.getTextLines(data, targetId);
			if (textLines) {
				const textCanvasCoordinates = [canvasCoordinates[0] + 6, canvasCoordinates[1] - 6];

				const textUID = "0";
				drawTextBoxSvg(
					svgDrawingHelper,
					annotationUID,
					textUID,
					textLines,
					[textCanvasCoordinates[0], textCanvasCoordinates[1]],
					options
				);
			}
		}

		return renderStatus;
	};
}

export default MyProbeTool;
